#include "run.h"
#include <string>
#include <iostream>
#include <regex>
#include <sstream>
std::string 
trim(std::string str){
  if(str.empty())
    return str;
  str.erase(0,str.find_first_not_of(" "));
  str.erase(str.find_last_not_of(" ")+1);
  str.erase(str.find_last_not_of("\n")+1);
  return str;
}
Runner::~Runner(){
  delete cf;
  delete history;
}
Command * 
Runner::parse_ACommand(const std::string &name,std::string content)const{
  Position pos = HEAD;
  if(name == "A")
    pos = TAIL;
  std::regex reg("\".*\"");
  content = trim(content);
  if(!regex_match(content,reg)){
    std::cerr << "Error:Content must wrapped by \"\"" << std::endl;
    return NULL;
  }
  return cf->create_ACommand(pos,content.substr(1,content.size()-2));
}
Command * 
Runner::parse_DCommand(const std::string &name,std::string content)const{
  Position pos = HEAD;
  if(name == "D")
    pos = TAIL;
  std::stringstream ss;
  ss << content;
  int len;
  ss >> std::ws >> len;
  return cf->create_DCommand(pos,len);
}
Command * 
Runner::analyze(std::string cmd_line){
  cmd_line = trim(std::move(cmd_line));
  int first_ws = cmd_line.find(" ");
  std::string name = (first_ws == std::string::npos || first_ws < 0)?cmd_line:cmd_line.substr(0,first_ws);
  if(name == "A" || name == "a"){ 
      if(first_ws == std::string::npos){
        std::cerr << "Error:lack of parameter of command " << name << std::endl;
        return NULL;
      }
      return parse_ACommand(name,cmd_line.substr(first_ws));
  }else if(name == "D" || name == "d"){
      if(first_ws == std::string::npos){
        std::cerr << "Error:lack of parameter of command " << name << std::endl;
        return NULL;
      }
      return parse_DCommand(name,cmd_line.substr(first_ws));
  }else if(name == "s")
      return cf->create_SCommand();
   else if(name == "lang"){
      if(first_ws == std::string::npos){
        std::cerr << "Error:lack of parameter of command " << name << std::endl;
        return NULL;
      }
      return cf->create_LanCommand(trim(cmd_line.substr(first_ws)));
   }
   else if(name == "content"){
      if(first_ws == std::string::npos){
        std::cerr << "Error:lack of parameter of command " << name << std::endl;
        return NULL;
      }
      return cf->create_ContextCommand(trim(cmd_line.substr(first_ws)));
   }else if(name == "l"){
      if(first_ws == std::string::npos){
        std::cerr << "Error:lack of parameter of command " << name << std::endl;
        return NULL;
      }
      int n;
      std::stringstream ss;
      ss << cmd_line.substr(first_ws);
      ss >> std::ws >> n;
      return cf->create_LCommand(n);
  }else if(name == "u")
      return cf->create_UCommand();
   else if(name == "r")
      return cf->create_RCommand();
   else if(name == "m"){
      if(first_ws == std::string::npos){
        std::cerr << "Error:lack of parameter of command " << name << std::endl;
        return NULL;
      }
      int n;
      std::string cmd_name;
      std::stringstream ss;
      ss << cmd_line.substr(first_ws);
      ss >> std::ws >> n;
      ss >> cmd_name;
      return cf->create_MDCommand(n,cmd_name);
  }else if(name == "spell")
      return cf->create_SPCommand();
   else if(name == "spell-a")
      return cf->create_SPACommand();
   else if(name == "spell-m")
      return cf->create_SPMCommand();
   else{
      if(name[0] == '$')
        return cf->create_MCommand(name.substr(1));
      else{
        std::cerr << "Error:Uknown command " << name << std::endl;
        return NULL;
      }
   }
}
std::string  
Runner::run(std::string cmd_line){
  Command *cmd = analyze(cmd_line);
  if(cmd != NULL){
    std::string result = cmd->execute();
    result = result.erase(result.find_last_not_of("\n")+1);
    history->record(cmd);
    return result;
  }
  return std::string("");
}
